home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Tools / macfreeze / macgen_bin.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  5.6 KB  |  204 lines

  1. """macgen_bin - Generate application from shared libraries"""
  2.  
  3. import os
  4. import sys
  5. import string
  6. import types
  7. import macfs
  8. from MACFS import *
  9. import Res
  10. import py_resource
  11. import cfmfile
  12. import buildtools
  13.  
  14.  
  15. def generate(input, output, module_dict = None, architecture = 'fat', debug=0):
  16.     # try to remove old file
  17.     try:
  18.         os.remove(output)
  19.     except:
  20.         pass
  21.     
  22.     if module_dict is None:
  23.         import macmodulefinder
  24.         print "Searching for modules..."
  25.         module_dict = macmodulefinder.process(input, [], [], 1)
  26.     
  27.     applettemplatepath = buildtools.findtemplate()
  28.     corepath = findpythoncore()
  29.     
  30.     dynamicmodules, dynamicfiles, extraresfiles = findfragments(module_dict, architecture)
  31.     
  32.     print 'Adding "__main__"'
  33.     buildtools.process(applettemplatepath, input, output, 0)
  34.     
  35.     outputref = Res.OpenResFile(output)
  36.     try:
  37.         Res.UseResFile(outputref)
  38.         
  39.         print "Adding Python modules"
  40.         addpythonmodules(module_dict)
  41.         
  42.         print "Adding PythonCore resources"
  43.         copyres(corepath, outputref, ['cfrg', 'Popt', 'GU\267I'], 1)
  44.         
  45.         print "Adding resources from shared libraries"
  46.         for ppcpath, cfm68kpath in extraresfiles:
  47.             if os.path.exists(ppcpath):
  48.                 copyres(ppcpath, outputref, ['cfrg'], 1)
  49.             elif os.path.exists(cfm68kpath):
  50.                 copyres(cfm68kpath, outputref, ['cfrg'], 1)
  51.         
  52.         print "Fixing sys.path prefs"
  53.         Res.UseResFile(outputref)
  54.         try:
  55.             res = Res.Get1Resource('STR#', 228) # from PythonCore
  56.         except Res.Error: pass
  57.         else:
  58.             res.RemoveResource()
  59.         # setting pref file name to empty string
  60.         res = Res.Get1NamedResource('STR ', "PythonPreferenceFileName")
  61.         res.data = Pstring("")
  62.         res.ChangedResource()
  63.         syspathpref = "$(APPLICATION)"
  64.         res = Res.Resource("\000\001" + Pstring(syspathpref))
  65.         res.AddResource("STR#", 229, "sys.path preference")
  66.         
  67.         print "Creating 'PYD ' resources"
  68.         for modname, (ppcfrag, cfm68kfrag) in dynamicmodules.items():
  69.             res = Res.Resource(Pstring(ppcfrag) + Pstring(cfm68kfrag))
  70.             id = 0
  71.             while id < 128:
  72.                 id = Res.Unique1ID('PYD ')
  73.             res.AddResource('PYD ', id, modname)
  74.     finally:
  75.         Res.CloseResFile(outputref)
  76.     print "Merging code fragments"
  77.     cfmfile.mergecfmfiles([applettemplatepath, corepath] + dynamicfiles.keys(), 
  78.             output, architecture)
  79.     
  80.     fss = macfs.FSSpec(output)
  81.     fss.SetCreatorType('Pyta', 'APPL')
  82.     print "done!"
  83.  
  84.  
  85. def findfragments(module_dict, architecture):
  86.     dynamicmodules = {}
  87.     dynamicfiles = {}
  88.     extraresfiles = []
  89.     for name, module in module_dict.items():
  90.         if module.gettype() <> 'dynamic':
  91.             continue
  92.         path = resolvealiasfile(module.__file__)
  93.         dir, filename = os.path.split(path)
  94.         ppcfile, cfm68kfile = makefilenames(filename)
  95.         
  96.         # ppc stuff
  97.         ppcpath = os.path.join(dir, ppcfile)
  98.         if architecture <> 'm68k':
  99.             ppcfrag, dynamicfiles = getfragname(ppcpath, dynamicfiles)
  100.         else:
  101.             ppcfrag = "_no_fragment_"
  102.         
  103.         # 68k stuff
  104.         cfm68kpath = os.path.join(dir, cfm68kfile)
  105.         if architecture <> 'pwpc':
  106.             cfm68kfrag, dynamicfiles = getfragname(cfm68kpath, dynamicfiles)
  107.         else:
  108.             cfm68kfrag = "_no_fragment_"
  109.         
  110.         dynamicmodules[name] = ppcfrag, cfm68kfrag
  111.         if (ppcpath, cfm68kpath) not in extraresfiles:
  112.             extraresfiles.append((ppcpath, cfm68kpath))
  113.     return dynamicmodules, dynamicfiles, extraresfiles
  114.  
  115.  
  116. def getfragname(path, dynamicfiles):
  117.     if not dynamicfiles.has_key(path):
  118.         if os.path.exists(path):
  119.             lib = cfmfile.CfrgResource(path)
  120.             fragname = lib.fragments[0].name
  121.         else:
  122.             print "shared lib not found:", path
  123.             fragname = "_no_fragment_"
  124.         dynamicfiles[path] = fragname
  125.     else:
  126.         fragname = dynamicfiles[path]
  127.     return fragname, dynamicfiles
  128.  
  129.  
  130. def addpythonmodules(module_dict):
  131.     # XXX should really use macgen_rsrc.generate(), this does the same, but skips __main__
  132.     items = module_dict.items()
  133.     items.sort()
  134.     for name, module in items:
  135.         mtype = module.gettype()
  136.         if mtype not in ['module', 'package'] or name == "__main__":
  137.             continue
  138.         location = module.__file__
  139.         
  140.         if location[-4:] == '.pyc':
  141.             # Attempt corresponding .py
  142.             location = location[:-1]
  143.         if location[-3:] != '.py':
  144.             print '*** skipping', location
  145.             continue
  146.         
  147.         print 'Adding module "%s"' % name
  148.         id, name = py_resource.frompyfile(location, name, preload=0, 
  149.                 ispackage=mtype=='package')
  150.  
  151. def Pstring(str):
  152.     if len(str) > 255:
  153.         raise TypeError, "Str255 must be at most 255 chars long"
  154.     return chr(len(str)) + str
  155.  
  156. def makefilenames(name):
  157.     lname = string.lower(name)
  158.     pos = string.find(lname, ".ppc.")
  159.     if pos > 0:
  160.         return name, name[:pos] + '.CFM68K.' + name[pos+5:]
  161.     pos = string.find(lname, ".cfm68k.")
  162.     if pos > 0:
  163.         return name[:pos] + '.ppc.' + name[pos+8:], name
  164.     raise ValueError, "can't make ppc/cfm68k filenames"
  165.  
  166. def copyres(input, output, *args, **kwargs):
  167.     openedin = openedout = 0
  168.     if type(input) == types.StringType:
  169.         input = Res.OpenResFile(input)
  170.         openedin = 1
  171.     if type(output) == types.StringType:
  172.         output = Res.OpenResFile(output)
  173.         openedout = 1
  174.     try:
  175.         apply(buildtools.copyres, (input, output) + args, kwargs)
  176.     finally:
  177.         if openedin:
  178.             Res.CloseResFile(input)
  179.         if openedout:
  180.             Res.CloseResFile(output)
  181.  
  182. def findpythoncore():
  183.     """find the PythonCore shared library, possibly asking the user if we can't find it"""
  184.     
  185.     vRefNum, dirID = macfs.FindFolder(kOnSystemDisk, kExtensionFolderType, 0)
  186.     extpath = macfs.FSSpec((vRefNum, dirID, "")).as_pathname()
  187.     version = string.split(sys.version)[0]
  188.     corepath = os.path.join(extpath, "PythonCore " + version)
  189.     if not os.path.exists(corepath):
  190.         fss, ok = macfs.PromptGetFile("Please locate PythonCore:", "shlb")
  191.         if not ok:
  192.             raise KeyboardInterrupt, "cancelled"
  193.         corepath = fss.as_pathname()
  194.     return resolvealiasfile(corepath)
  195.  
  196. def resolvealiasfile(path):
  197.     try:
  198.         fss, dummy1, dummy2 = macfs.ResolveAliasFile(path)
  199.     except macfs.error:
  200.         pass
  201.     else:
  202.         path = fss.as_pathname()
  203.     return path
  204.